package com.video.moderation.controller;

import com.alibaba.fastjson2.JSONObject;
import com.video.moderation.constant.SecurityConstants;
import com.video.moderation.entity.ChatMessage;
import com.video.moderation.entity.MemberLog;
import com.video.moderation.entity.VideoInfo;
import com.video.moderation.entity.VideoTag;
import com.video.moderation.entity.dto.OkHttpRes;
import com.video.moderation.entity.dto.Result;
import com.video.moderation.entity.model.ModerateForm;
import com.video.moderation.entity.vo.ChatDataVo;
import com.video.moderation.entity.vo.VideoDetailVo;
import com.video.moderation.entity.vo.VideoListVo;
import com.video.moderation.repository.*;
import com.video.moderation.utils.IpUtils;
import com.video.moderation.utils.JwtUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;
import okhttp3.RequestBody;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping("/video")
@Log4j2
public class VideoModerateController {

    private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");

    @Autowired
    private ChatMessageRepository chatMessageRepository;

    @Autowired
    private VideoInfoRepository videoInfoRepository;

    @Autowired
    private VideoInfoPageRepository videoInfoPageRepository;

    @Autowired
    private VideoTagRefRepository videoTagRefRepository;

    @Autowired
    private VideoTagRepository videoTagRepository;

    @Autowired
    private MemberLogRepository memberLogRepository;

    @Resource
    private JwtUtils jwtUtils;

    @GetMapping("/getVideoList")
    public Result getVideoList(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        Page<VideoListVo> res = videoInfoPageRepository.queryVideoList(pageable);
        return Result.success(res);
    }

    @GetMapping("/getVideoDetail")
    public Result getVideoDetail(@RequestParam("videoId") String videoId) {
        VideoDetailVo videoDetailVo = videoInfoPageRepository.queryVideoDetailById(videoId);
        List<String> labelList = new ArrayList<>();

        for (String tagId : videoTagRefRepository.queryTagIdByVid(videoId)) {
            VideoTag videoTag = videoTagRepository.findById(tagId).orElse(null);
            if (videoTag != null) labelList.add(videoTag.getTagName());
        }

        videoDetailVo.setLabelList(labelList);
        return Result.success(videoDetailVo);
    }

    @PostMapping("/moderate")
    public Result moderate(@org.springframework.web.bind.annotation.RequestBody ModerateForm moderateForm, HttpServletRequest httpServletRequest) {
        Long userId = moderateForm.getUserId();
        String videoId = moderateForm.getVideoId();
        Integer isPass = moderateForm.getIsPass();
        String[] reason = moderateForm.getReason();

        VideoInfo videoInfo = videoInfoRepository.findById(videoId).orElse(null);
        if (videoInfo == null) return Result.error("服务端异常");
        videoInfo.setStatus(isPass == 1 ? "1" : "2");
        videoInfoRepository.save(videoInfo);

        // 记录日志
        MemberLog memberLog = new MemberLog();
        String token = httpServletRequest.getHeader(SecurityConstants.AUTHORIZATION);
        memberLog.setMemberId(((Integer) jwtUtils.getClaims(token).get(SecurityConstants.MEMBER_ID)));
        memberLog.setBehavior("审核视频编号：" + videoId);
        memberLog.setIpAddr(IpUtils.getClientIP(httpServletRequest));
        memberLog.setLogTime(new Date());
        memberLogRepository.save(memberLog);

        OkHttpClient httpClient = new OkHttpClient();
        ChatMessage chatMessage = new ChatMessage();
        String strDateFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
        String passVideoInfo = "尊敬的用户，您好。您于" + sdf.format(videoInfo.getPublishTime()) + "，所上传的视频：" + videoInfo.getVideoTitle() + "，审核已通过";
        StringBuilder noPassInfo = new StringBuilder("尊敬的用户，您好。您于" + sdf.format(videoInfo.getPublishTime()) + "，所上传的视频：" + videoInfo.getVideoTitle() + "，审核未通过。原因可能包括：");

        // 判断是否存在pid，如果存在则使用，否则生成一个
        List<String> pid = chatMessageRepository.queryPid(1L, userId);
        if (pid != null && !pid.isEmpty()) chatMessage.setSession_id(pid.get(0));
        else chatMessage.setSession_id(UUID.randomUUID().toString());

        chatMessage.setFrom_user_id(1L);
        chatMessage.setTo_user_id(userId);
        
        if (isPass == 0) {
            for (String str : reason) {
                noPassInfo.append(str);
            }

            chatMessage.setContents(noPassInfo.toString());
        } else {
            chatMessage.setContents(passVideoInfo);
            // 异步存储索引
            Request request = new Request.Builder().url("http://127.0.0.1:8080/video/index/storeVideoIndex/" + videoId)
                    .post(RequestBody.create(null, new byte[0]))
                    .build();

            // 使用异步方式发送请求
            httpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    log.info("异步存储索引失败:", e);
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    log.info("异步存储索引成功 ");
                    response.close();
                }
            });
        }

        RequestBody body = RequestBody.create(MEDIA_TYPE, JSONObject.toJSONString(chatMessage));
        Request request = new Request.Builder().url("http://127.0.0.1:8080/chat/sendPrivateMessage").post(body).build();
        Response response = null;
        try {
            response = httpClient.newCall(request).execute();
            String jsonObj = response.body().string();
            OkHttpRes respRes = JSONObject.parseObject(jsonObj, OkHttpRes.class);

            if (respRes.getCode() == 200) {
                // 无法直接通过FastJson进行cast转换，因此手动进行转换
                ChatDataVo chatDataVo = new ChatDataVo();
                Map<String, String> item = respRes.getData();
                DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;

                chatDataVo.setChatId(Long.valueOf(item.get("chatId")));
                chatDataVo.setSessionId(item.get("sessionId"));
                chatDataVo.setSenderId(Long.valueOf(item.get("senderId")));
                chatDataVo.setSenderAvatar(item.get("senderAvatar"));
                chatDataVo.setSenderName(item.get("senderName"));
                chatDataVo.setContent(item.get("content"));
                chatDataVo.setReceiverId(Long.valueOf(item.get("receiverId")));
                chatDataVo.setReceiverAvatar(item.get("receiverAvatar"));
                chatDataVo.setReceiverName(item.get("receiverName"));
                chatDataVo.setChatTime(Date.from(OffsetDateTime.parse(item.get("chatTime"), formatter).toInstant()));

                // 将chatDataVo发送至Netty服务
                request = new Request.Builder().url("http://127.0.0.1:8979/websocket/" + chatDataVo.getSenderId()).build();
                httpClient.newWebSocket(request, new WebSocketListener() {
                    @Override
                    public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                        log.info("连接至Netty服务器失败");
                    }

                    @Override
                    public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
                        log.info("连接至Netty服务器成功");
                        webSocket.send(JSONObject.toJSONString(chatDataVo));
                    }
                });
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Result.success();
    }

}
